在前面的例子中,都是直接將資料放罝在記憶體之中,雖然使用方便,但也會出現對應的問題。
如果資料本身可以再重覆產生的類型,那還好處理。
若如果資料本身都具有獨特性、不可再重現性或是再現成本太過高,資料不見就會造成很大的麻煩。例如:金融的交易資訊,生理監控資訊、實驗即時數據。
因此,在某些情境下,系統必須確保資料內容不會因為異常終止,造成資料消失 。這個特性,又被稱為 持久性(Persistent)。
所以接下來,談談實現 Persistent 特性時,可考量的儲存介面。
將資料內容保存在 Memory 之中,是成本最低、最簡單的作法。像是實作使用的 ConcurrentQueue
或是 System.Collecitons.Generic
包含的 List
、Dictionary
都是這種。
選擇使用 Memory 時,需注意的部份如下:
如果要確保資料的存在,通常第一直覺就是採用檔案的方式,進行資料內容的存取操作。
也因為儲存到檔案,可操作的空間與靈活性就更大。可以儲存自訂格式的 BIN
檔,或是可以直接檢視內的的 Txt
、Json
。
也因為如此,選擇使用 File 時,需注意的部份如下;
I/O
所限制。當大量的存取時,I/O
速度是否會成為瓶頸,也需要考量。當然,存取資料的部份,也可以交給專業的 Database。對 database 而言,原子性 Atomicity
、一致性 Consistency
、隔離性 Isolation
、持久性 Durability
,這四種特性又被稱為 ACID,是 資料庫管理系統(DBMS)必須具備的。
目前可選擇的 database 有許多的類別,但可簡單區分為 NoSQL
、RDSDB
、Memory DB
三種。
選擇使用 Database 時,同樣的,也有必須評估的部份:
對資料的操作,不外乎就是讀取與寫入,但隨著系統越來越複雜,讀取:不會變更狀態的查詢與寫入:變更狀態的操作命令使用比例越來越大時,可能因為讀取的次數過多,間接影響寫入的效率;或是寫入時間過長,影響讀取的反應時間。
我們看一下,在 Microsoft 文件,是如何介紹 CQRS。
Command and Query Responsibility Segregation (CQRS) was introduced by Greg Young and strongly promoted by Udi Dahan and others. It is based on the CQS principle, although it is more detailed. It can be considered a pattern based on commands and events plus optionally on asynchronous messages. In many cases, CQRS is related to more advanced scenarios, like having a different physical database for reads (queries) than for writes (updates). Moreover, a more evolved CQRS system might implement Event-Sourcing (ES) for your updates database, so you would only store events in the domain model instead of storing the current-state data. However, this is not the approach used in this guide; we are using the simplest CQRS approach, which consists of just separating the queries from the commands.
依筆者自己的解讀,將引文內容簡釋一下。
當資料要寫入資料庫時,大多數的情況下,需要進行商業邏輯的運算,有可能運算時間就需要寫入時間的 N 倍之多。但是資料庫,為了確保資料交易的正確性,會將對應的資料區塊進行鎖定 Lock
。
造成查詢動作,必須等待交易完成後,才能進行。導致讀取資料反應時間過久,造成 Timeout 的現象。
圖片來源: From CQS to CQRS
在上面的圖,可以很精闢的說明,CQRS 將查詢與命令分開為兩條線的優點。
如果想要進一步再了解 CQRS,可以閱讀延伸閱讀內的文章。